<?php

/**
 * @category  Arc90_Service_Yammer
 * @package   Arc90_Service_Yammer
 * @author    Matt Williams <matt@mattwilliamsnyc.com>
 * @copyright Copyright (c) 2008 {@link http://arc90.com Arc90 Inc.}
 * @license   http://www.opensource.org/licenses/bsd-license.php
 */

/**
 * Software License Agreement (BSD License)
 * 
 * Copyright (c) 2008, Arc90 Inc.
 * All rights reserved.
 * 
 * Redistribution and use of this software in source and binary forms, with or
 * without modification, are permitted provided that the following conditions
 * are met:
 * 
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * 
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * 
 * - Neither the name of Arc90 Inc. nor the names of its contributors may be
 *   used to endorse or promote products derived from this software without
 *   specific prior written permission of Arc90 Inc.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @see Arc90_Service_Yammer_Exception
 */
require_once('Arc90/Service/Yammer/Exception.php');

/**
 * Arc90_Service_Yammer_Response provides methods for retrieving and acting on response data
 * from a {@link http://www.yammer.com Yammer} API call.
 *
 * Response data may be accessed as a {@link Arc90_Service_Yammer_Response::getDataString() string} or as an 
 * {@link Arc90_Service_Yammer_Response::getDataObject() object}. JSON response data is wrapped in a stdClass object.
 * XML data is wrapped in a {@link http://php.net/simplexml SimpleXmlElement}. 
 *
 * For convenience, response data may be accessed as direct object properties (e.g. $response->messages).
 *
 * HTTP request/response {@link http://php.net/curl_getinfo metadata} is also preserved and may be accessed via
 * {@link Arc90_Service_Yammer_Response::getHttpInfo() getHttpInfo()}. This data is returned as an array with the following keys:
 * <ul>
 *   <li>
 *     <b>url</b>:
 *     Target URL for the original request
 *   </li>
 *   <li>
 *     <b>content_type</b>:
 *     Content-type of downloaded object, NULL indicates server did not send valid 'Content-Type:' header
 *   </li>
 *   <li>
 *     <b>http_code</b>:
 *     HTTP status code sent with this response
 *   </li>
 *   <li>
 *     <b>header_size</b>:
 *     Total size of all response headers received
 *   </li>
 *   <li>
 *     <b>request_size</b>:
 *     Total size of issued requests
 *   </li>
 *   <li>
 *     <b>filetime</b>:
 *     Remote time of the retrieved document, if -1 is returned the time of the document is unknown
 *   </li>
 *   <li>
 *     <b>ssl_verify_result</b>:
 *     Result of SSL certification verification: Arc90_Service_Yammer does not currently request SSL verification
 *   </li>
 *   <li>
 *     <b>redirect_count</b>:
 *     Number of redirects followed during the request
 *   </li>
 *   <li>
 *     <b>total_time</b>:
 *     Total transaction time in seconds for last transfer
 *   </li>
 *   <li>
 *     <b>namelookup_time</b>:
 *     Time in seconds until name resolving was complete
 *   </li>
 *   <li>
 *     <b>connect_time</b>:
 *     Time in seconds it took to establish the connection
 *   </li>
 *   <li>
 *     <b>pretransfer_time</b>:
 *     Time in seconds from start until just before file transfer begins
 *   </li>
 *   <li>
 *     <b>size_upload</b>:
 *     Total number of bytes uploaded
 *   </li>
 *   <li>
 *     <b>size_download</b>:
 *     Total number of bytes downloaded
 *   </li>
 *   <li>
 *     <b>speed_download</b>:
 *     Average download speed
 *   </li>
 *   <li>
 *     <b>speed_upload</b>:
 *     Average upload speed
 *   </li>
 *   <li>
 *     <b>download_content_length</b>:
 *     Length of download, read from 'Content-Length' header
 *   </li>
 *   <li>
 *     <b>upload_content_length</b>:
 *     Specified size of upload
 *   </li>
 *   <li>
 *     <b>starttransfer_time</b>:
 *     Time in seconds until the first byte is about to be transferred
 *   </li>
 *   <li>
 *     <b>redirect_time</b>:
 *     Time in seconds of all redirection steps before final transaction was started
 *   </li>
 * </ul>
 *
 * @category  Arc90_Service_Yammer
 * @package   Arc90_Service_Yammer
 * @author    Matt Williams <matt@mattwilliamsnyc.com>
 * @copyright Copyright (c) 2008 {@link http://arc90.com Arc90 Inc.}
 * @license   http://www.opensource.org/licenses/bsd-license.php
 */
class Arc90_Service_Yammer_Response
{
    /**
     * HTTP metadata collected by cURL
     * @var    array
     * @access private
     */
    protected $_httpInfo = array();

    /**
     * Response body (if any) returned by Yammer, formatted as a string
     * @var    string
     * @access private
     */
    protected $_dataString = '';

    /**
     * Response body (if any) returned by Yammer, formatted as an object
     * @var    object
     * @access private
     */
    protected $_dataObject = NULL;

    /**
     * Creates a new Arc90_Service_Yammer_Response object.
     *
     * @param string $data Response data returned by Yammer
     * @param array  $info HTTP {@link http://us3.php.net/curl_getinfo metadata}
     */
    public function __construct($data, array $info)
    {
        $this->_dataString = $data;
        $this->_httpInfo   = $info;

        // If no error occurred, attempt to convert returned data to an object
        if(!$this->isError() && isset($info['url']))
        {
            // Convert JSON to StdClass object, XML to SimpleXMLElement
            if(strpos($info['url'], '.json'))
            {
                
                $this->_dataObject = @json_decode($data);
            }
            else if(strpos($info['url'], '.xml'))
            {
                $this->_dataObject = @simplexml_load_string($data);
            }
        }
    }

    /**
     * Overloads retrieval of object properties to allow access to response data.
     *
     * @param string $name Name of the property to be accessed
     *
     * @return mixed
     */
    public function __get($name)
    {
        // Delegate property access to dataObject if present
        return (NULL == $this->_dataObject) ? NULL : $this->_dataObject->$name;
    }

    /**
     * Overloads checking for existence of object properties to allow read-only access.
     *
     * @param  string $name Name of the property being checked
     * @return boolean
     */
    public function __isset($name)
    {
        // Delegate property access to dataObject if present
        return (NULL == $this->_dataObject) ? FALSE : isset($this->_dataObject->$name);
    }

    /**
     * Returns response data in original string format when response is converted to a string.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->_dataString;
    }

    /**
     * Returns response data in an object wrapper:
     * {@link http://us.php.net/manual/en/reserved.classes.php stdClass} for JSON content,
     * {@link http://php.net/simplexml SimpleXMLElement} for XML.
     *
     * @return object
     */
    public function getDataObject()
    {
        return $this->_dataObject;
    }

    /**
     * Returns the content body (if any) returned by Yammer.
     *
     * @return string
     */
    public function getDataString()
    {
        return $this->_dataString;
    }

    /**
     *
     * @return array
     */
    public function getHttpInfo()
    {
        return $this->_httpInfo;
    }

    /**
     * Checks for a non-2XX-class HTTP response status code.
     *
     * @return boolean
     */
    public function isError()
    {
        return 2 != floor($this->_httpInfo['http_code'] / 100);
    }

    /**
     * Returns response data (and metadata) as an associative array.
     *
     * @return array
     */
    public function toArray()
    {
        return array(
            'dataObject' => $this->_dataObject,
            'dataString' => $this->_dataString,
            'httpInfo'   => $this->_httpInfo
        );
    }
}
